import {
	ICtrlAbility,
	IEvent,
	IParam,
	IViewAbility,
	IViewActionResult,
	IViewModel,
	IProjectSetting,
	IAbility,
} from '@/core/interface';
import { IViewController } from '@/core/interface/view/controller';
import { IViewControllerParams } from '@/core/interface/view/controller-params';
import {
	IViewEvent,
	ViewActionType,
} from '@/core/interface/view/event/i-view-event';
import { IViewStore } from '@/core/interface/view/store';
import { LoadingHelper } from '@/core/modules';
import { deepCopy, LayoutUtil, verifyDynamicLogic } from '@/core/utils';
import { QXEvent } from 'qx-util';
import { ControllerBase } from '../common/controller-base';
import { useRoute } from 'vue-router';
import { useViewActionStoreWithOut } from '@/store';

/**
 * 视图控制器
 *
 * @export
 * @class ViewController
 * @implements {IViewController}
 */
export class ViewController<T, S extends IViewStore, A extends IViewAbility>
	extends ControllerBase<S, A>
	implements IViewController<S, A>
{
	/**
	 * 视图模型
	 *
	 * @type {IViewModel}
	 * @memberof ViewController
	 */
	protected declare readonly model: IViewModel;

	/**
	 * 视图抛出事件
	 *
	 * @protected
	 * @type {Function}
	 * @memberof GridViewController
	 */
	protected evt!: QXEvent<IViewEvent<T | ViewActionType, A>>;

	/**
	 * 视图是否默认加载
	 *
	 * @protected
	 * @type {boolean}
	 * @memberof GridViewController
	 */
	protected isLoadDefault = true;

	/**
	 * 视图打开方式
	 *
	 * @protected
	 * @type {('ROUTE' | 'EMBED' | 'MODAL')} 路由|嵌入|模态（默认路由）
	 * @memberof ViewController
	 */
	protected openType: 'ROUTE' | 'EMBED' | 'MODAL' = 'ROUTE';

	/**
	 * Creates an instance of ViewController.
	 * @param {IViewControllerParams} params
	 * @memberof ViewController
	 */
	constructor(params: IViewControllerParams<T | ViewActionType, A>) {
		super(params);
		this.viewInit(params);
	}

	/**
	 * 视图初始化
	 *
	 * @memberof ViewController
	 */
	public viewInit(params: IViewControllerParams<T | ViewActionType, A>): void {
		this.beforeViewInit(params);
		this.processViewInit(params);
		this.afterViewInit(params);
	}

	/**
	 * 视图初始化前（准备必要参数）
	 *
	 * @param {(IViewControllerParams<T | ViewActionType, A>)} params
	 * @memberof ViewController
	 */
	private beforeViewInit(params: IViewControllerParams<T | ViewActionType, A>) {
		this.evt = params.evt;
		this.isLoadDefault =
			this.model.isLoadDefault === true && params.isLoadDefault === true
				? true
				: false;
		this.openType = params.openType ? params.openType : 'ROUTE';
	}

	/**
	 * 处理视图初始化
	 *
	 * @param {(IViewControllerParams<T | ViewActionType, A>)} params
	 * @memberof ViewController
	 */
	protected processViewInit(
		params: IViewControllerParams<T | ViewActionType, A>
	) {
		this.store = {
			context: {},
			viewParams: {},
			closeView: this.closeView.bind(this),
			loadingHelper: new LoadingHelper('VIEW', params.pLoadingHelper),
			viewMsgs: [],
			counterData: {},
			layoutData: {},
			data: {},
			layoutModelDetails: {},
			toolbarItems: this.model.toolbarItems || [],
			viewCtx: {
				view: this,
				ctrl: {},
				appGlobal: {},
				routeViewGlobal: {},
				viewGlobal: {},
				viewNavData: {},
				parentView: undefined,
				rootView: undefined,
			},
		} as IViewStore as S;
	}

	/**
	 * 视图初始化后（对store做处理）
	 *
	 * @param {(IViewControllerParams<T | ViewActionType, A>)} params
	 * @memberof ViewController
	 */
	private afterViewInit(params: IViewControllerParams<T | ViewActionType, A>) {
		this.initStore();
		//	无部件抛出事件
		if (this.model.ctrls.length === 0) {
			this.evt.emit('viewInit', this.name, this.getAbility());
		}
	}

	/**
	 * 视图挂载
	 *
	 * @param {(IParam | undefined)} [opts]
	 * @memberof ViewController
	 */
	public viewMounted(opts: IParam = {}): void {
		this.initViewMsg();
		this.initCounterData();
		this.initViewActionState();
		if (this.UIEngineContainer) {
			const inputParam = this.getUIEngineInputParam();
			Object.assign(inputParam, { detailModel: this.store.toolbarItems });
			this.UIEngineContainer.executeViewEvent('onViewMounted', inputParam);
			this.UIEngineContainer.executeTimer(inputParam);
			this.UIEngineContainer.executeItemLogic(inputParam);
		}
		this.evt.emit('viewMounted', this.name, opts || {});
	}

	/**
	 * 初始化视图行为状态
	 *
	 * @memberof ViewController
	 */
	public initViewActionState() {
		const { fullPath } = useRoute();
		const { addAppViews } = useViewActionStoreWithOut();
		addAppViews(fullPath, this.model.codeName);
	}

	/**
	 * 视图销毁
	 *
	 * @memberof ViewController
	 */
	public viewDestroy(): void {
		this.destroyCounter();
		const projectSetting: IProjectSetting = App.getProjectSetting();
		if (!projectSetting.multiTabsSetting.show) {
			const { removeAppViewsByTag } = useViewActionStoreWithOut();
			removeAppViewsByTag(this.model.codeName);
		}
		if (this.UIEngineContainer) {
			const inputParam = this.getUIEngineInputParam();
			this.UIEngineContainer.executeViewEvent('onViewDestroyed', inputParam);
			this.UIEngineContainer.destroy();
		}
	}

	/**
	 * 关闭视图
	 *
	 * @memberof ViewController
	 */
	public closeView() {
		// 路由模式打开
		if (this.openType === 'ROUTE') {
			App.closeView();
		} else {
			this.emit('viewClose', this.getData());
		}
	}

	/**
	 * 刷新视图
	 *
	 * @memberof ViewController
	 */
	public refresh(args?: IParam): Promise<boolean> {
		return this.getMainCtrlAbility()?.refresh(args) || Promise.resolve(false);
	}

	/**
	 * 刷新父节点视图
	 *
	 * @memberof ViewController
	 */
	public refreshParentView(args?: IParam): Promise<boolean> {
		const { parentView } = this.store.viewCtx;
		if (!parentView) {
			return Promise.resolve(false);
		}
		return parentView.refresh(args);
	}

	/**
	 * 刷新root视图
	 *
	 * @memberof ViewController
	 */
	public refreshRootView(args?: IParam): Promise<boolean> {
		const { rootView } = this.store.viewCtx;
		if (!rootView) {
			return Promise.resolve(false);
		}
		return rootView.refresh(args);
	}

	/**
	 * 获取主部件能力
	 *
	 * @memberof ViewController
	 */
	protected getMainCtrlAbility(): ICtrlAbility | undefined {
		throw new Error('Method not implemented.');
	}

	/**
	 * 加载视图
	 *
	 * @memberof ViewController
	 */
	public load(args?: IParam): Promise<IViewActionResult> {
		throw new Error('Method not implemented.');
	}

	/**
	 * 保存视图
	 *
	 * @memberof ViewController
	 */
	public save(args?: IParam): void {
		this.emit('viewDataSave', []);
	}

	/**
	 * 处理部件初始化
	 *
	 * @param {string} name
	 * @param {ICtrlAbility} ability
	 * @memberof ViewController
	 */
	public handleCtrlInit(name: string, ability: ICtrlAbility): void {
		this.setSubAbility(name, ability);
		const controls = [];
		this.model.ctrls.forEach((ctrl) => {
			if (ctrl.controlType !== 'TOOLBAR' && ctrl.controlType !== 'SEARCHBAR') {
				controls.push(ctrl);
			}
		});
		if (this.subAbilityCenter.size === controls.length) {
			this.evt.emit('viewInit', this.name, this.getAbility());
		}
	}

	/**
	 * 处理部件行为
	 *
	 * @param {string} name
	 * @param {string} action
	 * @param {IParam[]} data
	 * @memberof ViewController
	 */
	public handleCtrlAction(name: string, action: string, data: IParam[]): void {
		// 后续处理
		if (this.UIEngineContainer) {
			const inputParam = this.getUIEngineInputParam();
			this.UIEngineContainer.executeCtrlEvent(action, inputParam);
		}
	}

	/**
	 * 处理部件销毁
	 *
	 * @param {string} name
	 * @param {IParam} data
	 * @memberof ViewController
	 */
	public handleCtrlDestroy(name: string, data: IParam) {
		throw new Error(`处理部件销毁暂未实现`);
	}

	/**
	 * 获取能力
	 *
	 * @return {*}  {A}
	 * @memberof ViewController
	 */
	public getAbility(): A {
		return {
			...super.getAbility(),
			closeView: this.closeView.bind(this),
			refresh: this.refresh.bind(this),
			load: this.load.bind(this),
			save: this.save.bind(this),
			getLayoutModelDetails: this.getLayoutModelDetails.bind(this),
			handlePanelValueChange: this.handlePanelValueChange.bind(this),
		};
	}

	/**
	 * 抛出视图行为
	 *
	 * @protected
	 * @param {(T )} action
	 * @param {IParam[]} data
	 * @memberof ViewController
	 */
	protected emit(action: T | ViewActionType, data: IParam[]) {
		this.evt.emit('viewAction', this.name, action, data);
	}

	/**
	 * 初始化视图消息组
	 *
	 * @return {*}  {A}
	 * @memberof ViewController
	 */
	public initViewMsg() {
		if (this.model.viewMsgGroupName) {
			App.getAppViewMsgHelper()
				.getViewMsgDetails(
					this.model.viewMsgGroupName,
					this.store.context,
					this.store.viewParams
				)
				.then((res: any) => {
					if (res?.length > 0) {
						this.store.viewMsgs = res;
					}
				});
		}
	}

	/**
	 * 初始化视图布局面板
	 *
	 * @return {*}
	 * @memberof ViewController
	 */
	protected async initLayout() {
		const { rootLayoutDetailNames, layoutItems } = this.model;
		if (rootLayoutDetailNames && layoutItems) {
			this.store.loadingHelper.beginLoading();
			for (let i = 0; i < rootLayoutDetailNames.length; i++) {
				const name = rootLayoutDetailNames[i];
				const rootItem = layoutItems[name];
				if (!rootItem) {
					return;
				}
				await this.initLayoutItem(rootItem);
			}
			if (this.UIEngineContainer) {
				const inputParam = this.getUIEngineInputParam();
				Object.assign(inputParam, { detailModel: this.store.toolbarItems });
				this.UIEngineContainer.executeItemLogic(inputParam);
			}
			this.store.loadingHelper.endLoading();
		}
	}

	/**
	 * 初始化布局项
	 *
	 * @param {*} layoutModelItem 项模型
	 * @param {number} [index] 多数据容器索引
	 * @memberof ViewController
	 */
	private async initLayoutItem(layoutModelItem: any, index?: number) {
		const { name } = layoutModelItem;
		const { layoutItems } = this.model;
		const { context, viewParams } = this.store;
		const layoutModelDetail = LayoutUtil.getLayoutItemInstance(
			{
				...layoutModelItem,
				viewType: this.model.viewType,
				panel: this,
			},
			context,
			viewParams
		);
		if (!(index || index === 0)) {
			await layoutModelDetail.load(context, viewParams);
			this.store.layoutModelDetails[name] = layoutModelDetail;
			this.store.layoutData[name] = layoutModelDetail.getData();
			this.panelLogic('');
		} else {
			layoutModelDetail.setIndex(index);
			await layoutModelDetail.load(context, viewParams);
			this.store.layoutModelDetails[`${name}_${index}`] = layoutModelDetail;
			this.store.layoutData[`${name}_${index}`] = layoutModelDetail.getData();
			this.panelLogic('', index);
		}
		if (layoutModelDetail && layoutModelDetail.details) {
			if (layoutModelDetail.dataRegionType === 'MULTIDATA') {
				const multiData = layoutModelDetail.getData();
				if (multiData && multiData.length > 0) {
					for (let i = 0; i < multiData.length; i++) {
						for (let j = 0; j < layoutModelDetail.details.length; j++) {
							const key = layoutModelDetail.details[j];
							if (layoutItems && layoutItems[key]) {
								await this.initLayoutItem(layoutItems[key], i);
							}
						}
					}
				}
			} else {
				for (let i = 0; i < layoutModelDetail.details.length; i++) {
					const key = layoutModelDetail.details[i];
					if (layoutItems && layoutItems[key]) {
						await this.initLayoutItem(layoutItems[key], index);
					}
				}
			}
		}
	}

	/**
	 * 面板逻辑
	 *
	 * @param {string} name
	 * @param {number} [index]
	 * @memberof ViewController
	 */
	private panelLogic(name: string, index?: number): void {
		const { layoutData } = this.store;
		const { layoutItems } = this.model;
		if (layoutItems) {
			Object.values(layoutItems).forEach((item: IParam) => {
				item.groupLogics?.forEach((logic: IParam) => {
					const relatedNames = logic.relatedDetailNames || [];
					if (Object.is(name, '') || relatedNames.indexOf(name) != -1) {
						const tempLogic = deepCopy(logic);
						if (index || index === 0) {
							tempLogic.childLogics.forEach((childLogic: any) => {
								childLogic.dEFDName = `${childLogic.dEFDName}_${index}`;
							});
						}
						const fullName =
							index || index === 0 ? `${item.name}_${index}` : item.name;
						const ret = verifyDynamicLogic(layoutData, tempLogic);
						switch (tempLogic.logicCat) {
							// 动态空输入，不满足则必填
							case 'ITEMBLANK':
								if (this.store.layoutModelDetails[fullName]) {
									this.store.layoutModelDetails[fullName].required = !ret;
								}
								break;
							// 动态启用，满足则启用
							case 'ITEMENABLE':
								if (this.store.layoutModelDetails[fullName]) {
									this.store.layoutModelDetails[fullName].disabled = !ret;
								}
								break;
							// 动态显示，满足则显示
							case 'PANELVISIBLE':
								if (this.store.layoutModelDetails[fullName]) {
									this.store.layoutModelDetails[fullName].visible = ret;
								}
								break;
						}
					}
				});
			});
		}
	}

	/**
	 * 处理面板值改变
	 *
	 * @private
	 * @param {string} name
	 * @param {*} value
	 * @param {number} [index]
	 * @return {*}
	 * @memberof ViewController
	 */
	private handlePanelValueChange(name: string, value: any, index?: number) {
		const fullName = index || index === 0 ? `${name}_${index}` : name;
		if (!fullName || !this.store.layoutData.hasOwnProperty(fullName)) {
			return;
		}
		this.store.layoutData[fullName] = value;
		this.store.layoutModelDetails[fullName].setData(value);
		this.panelLogic(name, index);
		this.computeButtonAuthState();
	}

	/**
	 * 处理面板按钮点击
	 *
	 * @private
	 * @param {string} name
	 * @param {*} event
	 * @param {number} [index]
	 * @memberof ViewController
	 */
	private handlePanelButtonAction(
		name: string,
		event: MouseEvent,
		index?: number
	) {
		const { context, viewParams } = this.store;
		const fullName = index || index === 0 ? `${name}_${index}` : name;
		const layoutModel = this.store.layoutModelDetails[fullName];
		if (layoutModel) {
			let tempData: IParam[] = [];
			const data: IParam = layoutModel.getData();
			const ability: any = layoutModel.getAbility();
			const logic = layoutModel.uiAction;
			if (data) {
				if (data instanceof Array) {
					tempData = [...data];
				} else {
					tempData = [data];
				}
			}
			App.getViewLogicHelper().executeViewLogic(
				context,
				viewParams,
				tempData,
				event,
				ability,
				logic
			);
		}
	}

	/**
	 * 计算面板按钮状态权限
	 *
	 * @memberof ViewController
	 */
	private async computeButtonAuthState() {
		for (const key in this.store.layoutModelDetails) {
			const layoutModel = this.store.layoutModelDetails[key];
			if (layoutModel.itemType == 'BUTTON') {
				await layoutModel.computeActionAuthState();
			}
		}
	}

	/**
	 * 处理组件行为
	 *
	 * @param {IEvent<string>} actionParam
	 * @memberof ViewController
	 */
	public handleComponentAction(
		actionParam: IEvent<string>,
		index?: number
	): void {
		const { name, action, data } = actionParam;
		switch (action) {
			case 'panelButtonAction':
				this.handlePanelButtonAction(name, data, index);
				break;
			case 'valueChange':
				this.handlePanelValueChange(name, data, index);
				this.handlePanelItemChange(name, data, index);
				break;
			case 'panelItemFocus':
			case 'editorFocus':
				this.handlePanelItemFocus(name, data, index);
				break;
			case 'panelItemBlur':
			case 'editorBlur':
				this.handlePanelItemBlur(name, data, index);
				break;
			case 'panelItemClick':
			case 'editorClick':
				this.handlePanelItemClick(name, data, index);
				break;
			default:
				break;
		}
	}

	/**
	 * @description 处理面板项变更
	 * @param {string} name
	 * @param {*} value
	 * @param {number} [index]
	 * @memberof ViewController
	 */
	public handlePanelItemChange(name: string, value: any, index?: number) {
		this.handlePanelItemLogic(name, value, 'onChange', index);
	}

	/**
	 * @description 处理面板项focus
	 * @param {string} name
	 * @param {*} value
	 * @param {number} [index]
	 * @memberof ViewController
	 */
	public handlePanelItemFocus(name: string, value: any, index?: number) {
		this.handlePanelItemLogic(name, value, 'onEnter', index);
	}

	/**
	 * @description 处理面板项blur
	 * @param {string} name
	 * @param {*} value
	 * @param {number} [index]
	 * @memberof ViewController
	 */
	public handlePanelItemBlur(name: string, value: any, index?: number) {
		this.handlePanelItemLogic(name, value, 'onLeave', index);
	}

	/**
	 * @description 处理面板项点击
	 * @param {string} name
	 * @param {*} value
	 * @param {number} [index]
	 * @memberof ViewController
	 */
	public handlePanelItemClick(name: string, value: any, index?: number) {
		this.handlePanelItemLogic(name, value, 'onClick', index);
	}

	/**
	 * @description 处理面板项逻辑
	 * @param {string} name
	 * @param {*} value
	 * @param {string} action
	 * @param {number} [index]
	 * @memberof ViewController
	 */
	public handlePanelItemLogic(
		name: string,
		value: any,
		action: string,
		index?: number
	) {
		const fullName = index || index === 0 ? `${name}_${index}` : name;
		if (!fullName || !this.store.layoutData.hasOwnProperty(fullName)) {
			return;
		}
		if (this.UIEngineContainer) {
			const inputParam = this.getUIEngineInputParam();
			this.UIEngineContainer.executePanelEvent(
				`${fullName}${action}`,
				inputParam
			);
		}
	}

	/**
	 * 获取布局面板模型对象
	 *
	 * @memberof ViewController
	 */
	public getLayoutModelDetails() {
		return this.store.layoutModelDetails;
	}
}
